﻿package smooth.core.object.googleMapLayerComponent {
	import app.core.action.RotatableScalable;
	import app.core.action.RotatableScalableChangedEvent;
	import com.google.maps.LatLng;
	import com.google.maps.LatLngBounds;
	import com.google.maps.overlays.Polyline;
	import com.google.maps.overlays.PolylineOptions;
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.geom.Point;
	import flash.filters.*;
	import flash.events.*;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import smooth.core.object.googleMapComponent.MapChangedEvent;
	import smooth.core.object.interactiveTextComponent.InteractiveTextComponent;
	import smooth.core.object.localizationComponent.LocalizationComponent;
	import smooth.core.object.googleMapComponent.GoogleMapsPureASComponent;
	import smooth.core.object.googleMapComponent.TappableMap;
	
	
	public class GoogleMapLayerComponent extends RotatableScalable {	
		public static const HYBRID_MAP_TYPE:int = 0;
		public static const NORMAL_MAP_TYPE:int = 1;
		public static const PHYSICAL_MAP_TYPE:int = 2;
		public static const SATELLITE_MAP_TYPE:int = 3;
		
		private var clickgrabber:Shape = new Shape();
		private var googleMapObject:GoogleMapsPureASComponent;
		private var menu:GoogleMapLayerMenu;
		private var resizedStatus:Boolean;
		private var drawStatus:Boolean;
		private var initialWidth:int;
		private var initialHeight:int;
		private var initialPosX:int;
		private var initialPosY:int;
		private var initialColor:int;
		private var initialMapType:int;
		private var initialCenter:LatLng;
		private var initialZoom:Number;
		
		private var drawFromPoint:LatLng;
		private var defaultPolylineOptions:PolylineOptions;
				
		public function GoogleMapLayerComponent(posX:int, posY:int, sizeX:int, sizeY:int, color:int, initialMapType:int, initialCenter:LatLng, initialZoom:Number)	{
			// Init des attributs de l'objet
			this.initialPosX = posX;
			this.initialPosY = posY;
			this.initialWidth = sizeX;
			this.initialHeight = sizeY;
			this.initialColor = color;
			this.initialMapType = initialMapType;
			this.initialCenter = initialCenter;
			this.initialZoom = initialZoom;
			this.noRotate = true;
			this.noScale = true;
			this.freezedStatus = false;
			this.resizedStatus = false;
			this.drawStatus = false;
			// Init des process du composant
			initProcess();
			// Init des visuels du composant			
			initGraphics();
			// Init des events du composant
			initEvents();	
		}	
		
		private function initGraphics():void {
			this.clickgrabber.graphics.lineStyle(6,this.initialColor, 1);
			this.clickgrabber.graphics.beginFill(this.initialColor, 0);
			this.clickgrabber.graphics.drawRect(0, 0, this.initialWidth, this.initialHeight);
			this.clickgrabber.graphics.endFill();
			this.addChildAt(this.clickgrabber, 0);
			this.x = this.initialPosX;
			this.y = this.initialPosY;
			
			// Polyline options
			var defaultPolylineOptions:PolylineOptions = new PolylineOptions({strokeStyle:{thickness:5, color:this.initialColor, alpha:1, pixelHinting:false }} );
			PolylineOptions.setDefaultOptions(this.defaultPolylineOptions);
		}
		
		private function initProcess():void {
			this.googleMapObject = new GoogleMapsPureASComponent(0, 0, this.initialWidth, this.initialHeight, this.initialMapType, this.initialCenter, this.initialZoom, true, false);
			this.addChildAt(this.googleMapObject, this.numChildren);
			this.menu = new GoogleMapLayerMenu(this.initialWidth, 0, this.initialColor);
			this.addChild(this.menu);
		}
		
		private function initEvents():void {
		}
		
		public function doCreateMarker(point:Point, lat:Number, lng:Number, container:DisplayObject):void {
			var label:String = "Lat:" + lat + " / Long:" + lng;
			var localContainer:TappableMap = container as TappableMap;
			var localization1:LocalizationComponent = new LocalizationComponent(container.localToGlobal(point), lat, lng, label);
			this.stage.addChild(localization1);
		}
		
		public function isResized():Boolean {
			return this.resizedStatus;
		}
		
		public function isDrawing():Boolean {
			return this.drawStatus;
		}
		
		public function getColor():Number {
			return this.initialColor;
		}
		
		public function fromLatLngToViewport(latLng:LatLng):Point {
			return this.googleMapObject.fromLatLngToViewport(latLng);
		}
		
		public function globalToLocalMap(point:Point):Point {
			return this.googleMapObject.globalToLocalMap(point);
		}
		
		public function localMapToGlobal(point:Point):Point {
			return this.googleMapObject.localMapToGlobal(point);
		}
		
		public function getCenter():LatLng {
			return this.googleMapObject.getCenter();
		}
		
		public function getLatLngBounds():LatLngBounds {
			return this.googleMapObject.getLatLngBounds();
		}
		
		public function setCenter(latLng:LatLng):void {
			this.googleMapObject.setCenter(latLng);
		}
		
		public function setZoom(zoom:Number):void {
			this.googleMapObject.setZoom(zoom);
		}
		
		public function getMapUniqueId():Number {
			return this.googleMapObject.getUniqueId();
		}
		
		public function zoomIn(latLng:LatLng, centerOnPoint:Boolean=false):void {
			this.googleMapObject.zoomIn(latLng, centerOnPoint);
		}
		
		public function zoomOut(latLng:LatLng):void {
			this.googleMapObject.zoomOut(latLng);
		}
		
		public function setMapType(mapType:int):void {
			switch (mapType) {
				case HYBRID_MAP_TYPE:
					this.googleMapObject.setMapType(GoogleMapsPureASComponent.HYBRID_MAP_TYPE);
					break;
				case NORMAL_MAP_TYPE:
					this.googleMapObject.setMapType(GoogleMapsPureASComponent.NORMAL_MAP_TYPE);
					break;
				case PHYSICAL_MAP_TYPE:
					this.googleMapObject.setMapType(GoogleMapsPureASComponent.PHYSICAL_MAP_TYPE);
					break;
				case SATELLITE_MAP_TYPE:
					this.googleMapObject.setMapType(GoogleMapsPureASComponent.SATELLITE_MAP_TYPE);
					break;
			}
		}
		
		private function refreshLayerAfterRotateScaled(e:RotatableScalableChangedEvent):void {
			this.googleMapObject.scaleX = 1/this.scaleX;
			this.googleMapObject.scaleY = 1/this.scaleY;
			this.googleMapObject.getMap().scaleX = 1/this.scaleX;
			this.googleMapObject.getMap().scaleY = 1/this.scaleY;
			this.googleMapObject.setSize(new Point(this.initialWidth*this.scaleX, this.initialHeight*this.scaleY));
			this.parent.doRefreshAllLayers();
		}
		
		public function removeComponent():void {
			// START - 20081119 - LSA
			this.stopFreeze();
			// END - 20081119 - LSA
			switch (initialMapType) {
				case HYBRID_MAP_TYPE:
					this.parent.doCloseHybridMapLayer();
					break;
				case NORMAL_MAP_TYPE:
					this.parent.doCloseNormalMapLayer();
					break;
				case PHYSICAL_MAP_TYPE:
					this.parent.doClosePhysicalMapLayer();
					break;
			}
		}
		
		public function freeze():void {
			this.freezedStatus = true;
			this.googleMapObject.setFreezeStatus(true);
			this.noRotate = true;
			this.noScale = true;
			this.noMove = true;
			this.addEventListener(TouchEvent.MOUSE_MOVE, this.forwardToParentMap, false, 0, true);			
			this.addEventListener(TouchEvent.MOUSE_DOWN, this.forwardToParentMap, false, 0, true);						
			this.addEventListener(TouchEvent.MOUSE_UP, this.forwardToParentMap, false, 0, true);									
			this.addEventListener(TouchEvent.MOUSE_OVER, this.forwardToParentMap, false, 0, true);									
			this.addEventListener(TouchEvent.MOUSE_OUT, this.forwardToParentMap, false, 0, true);		
		}
		
		public function stopFreeze():void {
			this.freezedStatus = false;
			this.googleMapObject.setFreezeStatus(false);
			this.noRotate = true;
			this.noScale = true;
			this.noMove = false;
			this.removeEventListener(TouchEvent.MOUSE_MOVE, this.forwardToParentMap, false);			
			this.removeEventListener(TouchEvent.MOUSE_DOWN, this.forwardToParentMap, false);						
			this.removeEventListener(TouchEvent.MOUSE_UP, this.forwardToParentMap, false);									
			this.removeEventListener(TouchEvent.MOUSE_OVER, this.forwardToParentMap, false);									
			this.removeEventListener(TouchEvent.MOUSE_OUT, this.forwardToParentMap, false);		
		}
		
		private function forwardToParentMap(e:TouchEvent):void {
			var tm:TappableMap = this.parent.getMap();
			tm.dispatchEvent(e);
			e.stopPropagation();
		}
		
		public function resize():void {
			this.resizedStatus = true;
			this.googleMapObject.setFreezeStatus(true);
			this.noRotate = true;
			this.noScale = false;
			this.noMove = true;
			this.addEventListener(RotatableScalableChangedEvent.rotateScaled, refreshLayerAfterRotateScaled);
		}
		
		public function stopResize():void {
			this.resizedStatus = false;
			// START - 20081116 - LSA
			this.googleMapObject.setFreezeStatus(false);
			// END - 20081116 - LSA
			this.noRotate = true;
			this.noScale = true;
			this.noMove = false;
			this.removeEventListener(RotatableScalableChangedEvent.rotateScaled, refreshLayerAfterRotateScaled);
		}
		
		public function draw():void {
			this.drawStatus = true;
			this.noRotate = true;
			this.noScale = true;
			this.noMove = true;
			this.googleMapObject.setFreezeStatus(true);
			this.addEventListener(TouchEvent.MOUSE_DOWN, startDraw);
			// Remove EventListeners for freeze action
			this.removeEventListener(TouchEvent.MOUSE_MOVE, this.forwardToParentMap, false);			
			this.removeEventListener(TouchEvent.MOUSE_DOWN, this.forwardToParentMap, false);						
			this.removeEventListener(TouchEvent.MOUSE_UP, this.forwardToParentMap, false);									
			this.removeEventListener(TouchEvent.MOUSE_OVER, this.forwardToParentMap, false);									
			this.removeEventListener(TouchEvent.MOUSE_OUT, this.forwardToParentMap, false);		
		}
		
		public function stopDraw():void {
			trace("GoogleMapLayerComponent::stopDraw");
			this.drawStatus = false;
			this.noRotate = true;
			this.noScale = true;
			this.noMove = false;
			this.removeEventListener(TouchEvent.MOUSE_DOWN, startDraw);
			this.removeEventListener(TouchEvent.MOUSE_MOVE, drawLine);
			this.removeEventListener(TouchEvent.MOUSE_UP, endDraw);
			// add freeze listeners for freeze action
			this.addEventListener(TouchEvent.MOUSE_MOVE, this.forwardToParentMap, false, 0, true);			
			this.addEventListener(TouchEvent.MOUSE_DOWN, this.forwardToParentMap, false, 0, true);						
			this.addEventListener(TouchEvent.MOUSE_UP, this.forwardToParentMap, false, 0, true);									
			this.addEventListener(TouchEvent.MOUSE_OVER, this.forwardToParentMap, false, 0, true);									
			this.addEventListener(TouchEvent.MOUSE_OUT, this.forwardToParentMap, false, 0, true);		
		}
		
		private function startDraw(e:TouchEvent):void {
			trace("GoogleMapLayerComponent::startDraw");
			// START - 20081117 - LSA
			//var currentDrawingPoint:Point = this.localToGlobal(new Point(e.localX, e.localY));
			var currentDrawingPoint:Point = this.localToGlobal(new Point(e.localX/this.scaleX, e.localY/this.scaleY));
			// END - 20081117 - LSA
			var currentDrawingNormalizedToMap:Point = this.googleMapObject.globalToLocalMap(currentDrawingPoint);
			this.drawFromPoint = this.googleMapObject.fromViewportToLatLng(currentDrawingNormalizedToMap);
			this.addEventListener(TouchEvent.MOUSE_MOVE, drawLine);
			this.addEventListener(TouchEvent.MOUSE_UP, endDraw);
			this.removeEventListener(TouchEvent.MOUSE_DOWN, startDraw);
			e.stopPropagation();
		}
		
		private function drawLine(e:TouchEvent):void {
			trace("GoogleMapLayerComponent::drawLine");
			// START - 20081117 - LSA
			//var currentDrawingPoint:Point = this.localToGlobal(new Point(e.localX, e.localY));
			var currentDrawingPoint:Point = this.localToGlobal(new Point(e.localX/this.scaleX, e.localY/this.scaleY));
			// END - 20081117 - LSA
			var currentDrawingNormalizedToMap:Point = this.googleMapObject.globalToLocalMap(currentDrawingPoint);
			var drawToPoint:LatLng = this.googleMapObject.fromViewportToLatLng(currentDrawingNormalizedToMap);
			var line:Polyline = new Polyline(new Array(this.drawFromPoint, drawToPoint), this.defaultPolylineOptions);
			line.visible = true;
			this.googleMapObject.addOverlay(line);
			this.drawFromPoint = drawToPoint;
			e.stopPropagation();
		}
		
		private function endDraw(e:TouchEvent):void {
			trace("GoogleMapLayerComponent::endDraw");
			this.removeEventListener(TouchEvent.MOUSE_MOVE, drawLine);
			this.removeEventListener(TouchEvent.MOUSE_UP, endDraw);
			this.addEventListener(TouchEvent.MOUSE_DOWN, startDraw);
			e.stopPropagation();
		}
		
	}
}

